package com.hyt.it.ogt.ks.service.impl;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import javax.annotation.Resource;

import com.hyt.it.ogt.ks.service.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.hyt.common.apiInfor.ApiResponse;
import com.hyt.it.ogt.ks.config.ConfigManager;
import com.hyt.it.ogt.ks.config.KsBizRunTimeException;
import com.hyt.it.ogt.ks.enums.BizStatusCode;
import com.hyt.it.ogt.ks.enums.PaperItemTypeCode;
import com.hyt.it.ogt.ks.enums.TranslateLanguageCode;
import com.hyt.it.ogt.ks.feign.KwClient;
import com.hyt.it.ogt.ks.mapper.PaperTopicMapper;
import com.hyt.it.ogt.ks.model.entity.CandidateAnswer;
import com.hyt.it.ogt.ks.model.entity.CandidatePaper;
import com.hyt.it.ogt.ks.model.entity.PaperTopic;
import com.hyt.it.ogt.ks.model.vo.PaperBigQuestionVO;
import com.hyt.it.ogt.ks.model.vo.PaperQuestionVO;
import com.hyt.it.ogt.ks.model.vo.TopicOptionVO;
import com.hyt.it.ogt.ks.model.vo.paper.PItemDTO;
import com.hyt.it.ogt.ks.model.vo.paper.POptionDTO;
import com.hyt.it.ogt.ks.model.vo.paper.PTopicDTO;
import com.hyt.it.ogt.ks.util.Constants;
import com.hyt.it.ogt.ks.util.KeyDefineCommon;

import lombok.extern.slf4j.Slf4j;

/**
 * <p>
 * 试卷相关实现类
 * </p>
 *
 * @author 刘恒活
 * @since 2020-06-17
 */
@Slf4j
@Service
public class PaperServiceImpl implements IPaperService {
    @Resource
    private IExamCacheService iExamCacheService;
    @Resource
    private ICandidatePaperService iCandidatePaperService;
    @Resource
    private ICandidateAnswerService iCandidateAnswerService;
    @Resource
    private KwClient kwClient;
    @Resource
    private ConfigManager configManager;
    @Resource
    private RedisTemplate redisTemplate;
    @Resource
    private PaperTopicMapper paperTopicMapper;
    @Resource
    private IAnswerProgressService iAnswerProgressService;

    @Override
    public void getPaper() {
    }

    @Override
    public Integer getItemNumberByTopicId(String paperId, String paperVersion, String topicId) {
        if(Constants.PAPER_FROM_BY_CACHE.equalsIgnoreCase(configManager.getPaperFrom())) {
            return iExamCacheService.getItemNumberByTopicId(paperId, paperVersion, topicId);
        } else {
            return null;
        }
    }

    @Override
    public PTopicDTO getTopic(String paperId, String paperVersion, String topicId) {
        if(Constants.PAPER_FROM_BY_CACHE.equalsIgnoreCase(configManager.getPaperFrom())) {
            return iExamCacheService.getPaperTopicFromCache(paperId, paperVersion, topicId);
        } else {
            return this.getTopicByKw(paperId, paperVersion, topicId);
        }
    }

    private PTopicDTO getTopicByKw(String paperId, String paperVersion, String topicId) {
        String json = kwClient.getTopic(paperId, paperVersion, topicId);
        ApiResponse<JSONObject> apiResponse = JSON.parseObject(json, ApiResponse.class);
        if(apiResponse.getCode().intValue() == BizStatusCode.KW_SUCCESS_OK.getCode().intValue()){
            return JSON.parseObject(apiResponse.getData().toJSONString(), PTopicDTO.class);
        } else {
            return null;
        }
    }

    @Override
    public Map<String, PItemDTO> getPaperItemByTopicId(String paperId, String paperVersion, String topicId) {
        if(Constants.PAPER_FROM_BY_CACHE.equalsIgnoreCase(configManager.getPaperFrom())) {
            return iExamCacheService.getPaperItemByTopicId(paperId, paperVersion, topicId);
        } else {
            return this.getPaperItemByTopicIdFromKw(paperId, paperVersion, topicId);
        }
    }

    private Map<String, PItemDTO> getPaperItemByTopicIdFromKw(String paperId, String paperVersion, String topicId) {
        String json = kwClient.getPaperItemByTopicId(paperId, paperVersion, topicId);
        ApiResponse<JSONObject> apiResponse = JSON.parseObject(json, ApiResponse.class);
        if(apiResponse.getCode().intValue() == BizStatusCode.KW_SUCCESS_OK.getCode().intValue()){
            Map<String, JSONObject> map = JSON.parseObject(apiResponse.getData().toJSONString(), Map.class);
            Map<String, PItemDTO> itemMap = new HashMap<>();
            map.forEach((k, v) -> {
                PItemDTO item = JSON.parseObject(v.toJSONString(), PItemDTO.class);
                itemMap.put(k, item);
            });
            return itemMap;
        } else {
            return null;
        }
    }

    @Override
    public PItemDTO getPItem(String paperId, String paperVersion, String itemId) {
        if(Constants.PAPER_FROM_BY_CACHE.equalsIgnoreCase(configManager.getPaperFrom())) {
            return iExamCacheService.getPaperItemFromCache(paperId, paperVersion, itemId);
        } else {
            return this.getPItemFromKw(paperId, paperVersion, itemId);
        }
    }

    private PItemDTO getPItemFromKw(String paperId, String paperVersion, String itemId) {
        String json = kwClient.getItem(paperId, paperVersion, itemId);
        ApiResponse<JSONObject> apiResponse = JSON.parseObject(json, ApiResponse.class);
        if(apiResponse.getCode().intValue() == BizStatusCode.KW_SUCCESS_OK.getCode().intValue()){
            return JSON.parseObject(apiResponse.getData().toJSONString(), PItemDTO.class);
        } else {
            return null;
        }
    }

    /**
     * 试卷初始化的时候也会放缓存，实际用到缓存没有，也会查数据库放缓存
     * @param examId
     * @param candidateId
     * @param paperSort
     * @return
     */
    @Override
    public CandidatePaper getCandidatePaperFromCache(String examId, String candidateId, Integer paperSort) {
        String key = KeyDefineCommon.getCandidatePaperKey(examId, candidateId, paperSort);
        Object val = redisTemplate.opsForValue().get(key);
        if(val == null) {
            return this.putCandidatePaperFromCache(examId, candidateId, paperSort, 6, TimeUnit.HOURS);
        } else {
            return JSON.parseObject(val.toString(), CandidatePaper.class);
        }
    }

    @Override
    public CandidatePaper putCandidatePaperFromCache(String examId, String candidateId, Integer paperSort,
                                                     Integer timeout, TimeUnit timeUnit) {
        String key = KeyDefineCommon.getCandidatePaperKey(examId, candidateId, paperSort);
        CandidatePaper candidatePaper = iCandidatePaperService.getOne(Wrappers.<CandidatePaper>lambdaQuery()
                .select(CandidatePaper::getPaperId, CandidatePaper::getPaperVersion, CandidatePaper::getPaperType,
                        CandidatePaper::getId)
                .eq(CandidatePaper::getExamId, examId).eq(CandidatePaper::getCandidateId, candidateId)
                .eq(CandidatePaper::getMixSort, paperSort).last("limit 1"));
        redisTemplate.opsForValue().set(key, JSON.toJSONString(candidatePaper), timeout, timeUnit);
        return candidatePaper;
    }

    @Override
    public CandidateAnswer getItemAnswer(String examId, String candidateId, String itemId, Integer paperSort, String language) {
        CandidatePaper candidatePaper = this.getCandidatePaperFromCache(examId, candidateId, paperSort);
        CandidateAnswer answer = iCandidateAnswerService.lambdaQuery()
                .select(CandidateAnswer::getItemMixSort, CandidateAnswer::getOptionMixSortRule,
                        CandidateAnswer::getId, CandidateAnswer::getSubjectiveAnswer,CandidateAnswer::getItemType)
                        .eq(CandidateAnswer::getExamId, examId)
                        .eq(CandidateAnswer::getCandidateId, candidateId)
                        .eq(CandidateAnswer::getPaperId, candidatePaper.getPaperId())
                        .eq(CandidateAnswer::getPaperVersion, candidatePaper.getPaperVersion())
                        .eq(CandidateAnswer::getDelFlag, false)
                        .eq(CandidateAnswer::getItemId, itemId).one();
        return answer;
    }

    @Override
    public PItemDTO getItemContent(String examId, String candidateId, String itemId, Integer paperSort, String language) {
        CandidatePaper candidatePaper = this.getCandidatePaperFromCache(examId, candidateId, paperSort);
        if(Objects.isNull(candidatePaper)) {
            return null;
        }
        return this.getPItem(candidatePaper.getPaperId(), candidatePaper.getPaperVersion(), itemId);
    }

    @Override
    public PaperBigQuestionVO getItem(String candidateId, String examId, String itemId, Integer paperSort
            , String language,Integer childItemSort) {
        PaperBigQuestionVO paperTopic = new PaperBigQuestionVO();
        // 获取试卷
        CandidatePaper candidatePaper = this.getCandidatePaperFromCache(examId, candidateId, paperSort);
        // 是否练习模式，用于是否向前端显示标答和答案解析
        boolean isPracticeMode = iExamCacheService.isPracticeMode(examId);

        // 从考务获取小题信息，如是复合题，则会把复合题下的子小题也查询过来
        PItemDTO item = this.getPItem(candidatePaper.getPaperId(), candidatePaper.getPaperVersion(), itemId);
        //log.info("获取小题:【{}】", JSON.toJSONString(item));
        // 获取小题及作答答案
        CandidateAnswer answer = iCandidateAnswerService.getOne(
                Wrappers.<CandidateAnswer>lambdaQuery()
                        .select(CandidateAnswer::getItemMixSort, CandidateAnswer::getOptionMixSortRule, CandidateAnswer::getFullScore)
                        .eq(CandidateAnswer::getExamId, examId)
                        .eq(CandidateAnswer::getCandidateId, candidateId)
                        .eq(CandidateAnswer::getPaperId, candidatePaper.getPaperId())
                        .eq(CandidateAnswer::getPaperVersion, candidatePaper.getPaperVersion())
                        .eq(CandidateAnswer::getDelFlag, false)
                        .eq(CandidateAnswer::getItemId, itemId).last("limit 1"));

        //如果开启了不能回退，复合题，案例分析题刚要一次给一个小题
        if (PaperItemTypeCode.ITEM_TYPE_COMPOUND_CODE.getCode().equalsIgnoreCase(item.getItemType())
                || PaperItemTypeCode.ITEM_TYPE_CASE_ANALYSIS_CODE.getCode().equalsIgnoreCase(item.getItemType())){
            //先去掉的原因是因为，当考生在考试过程，如果去掉了限制回退，那么考试中的考生不能受影响
            /*List<ExamConfigVO> examConfigs = Optional.ofNullable(iExamCacheService.getExamConfigCache(examId))
                    .orElseThrow(() -> new KsBizRunTimeException());
            examConfigs = examConfigs.stream().filter(
                    l -> l.getConfigCode().equals(ExamConfigCode.EXAM_CONFIG_CODE_LIMIT_BACK.getCode())
            ).collect(Collectors.toList());
            Boolean answerLimitBack = examConfigs.size() == 1 && examConfigs.get(0).getConfigValue().equals("true");*/
            if(/*answerLimitBack &&*/ Objects.nonNull(childItemSort)){//todo
                CandidateAnswer answerChild = iCandidateAnswerService.getOne(
                        Wrappers.<CandidateAnswer>lambdaQuery().select(CandidateAnswer::getItemId,
                                        CandidateAnswer::getItemMixSort, CandidateAnswer::getOptionMixSortRule)
                                .eq(CandidateAnswer::getExamId, examId)
                                .eq(CandidateAnswer::getCandidateId, candidateId)
                                .eq(CandidateAnswer::getPaperId, candidatePaper.getPaperId())
                                .eq(CandidateAnswer::getPaperVersion, candidatePaper.getPaperVersion())
                                .eq(CandidateAnswer::getParentItemId, itemId)
                                .eq(CandidateAnswer::getDelFlag, false)
                                .eq(CandidateAnswer::getItemMixSort, childItemSort).last("limit 1"));
                // 考务已经封装好子小题传过来
                PItemDTO childItem = item.getChildItemMap().get(answerChild.getItemId());
                // 构造小题信息
                paperTopic.setItemData(this.buildPaperItem(childItem, answerChild, isPracticeMode,examId,candidateId,paperSort));
                //将所属大题的题干信息带给前端
                paperTopic.getItemData().setParentItemContent(item.getItemContent());
                //将所属大题的总分值信息带给前端
                paperTopic.getItemData().setParentScore(answer.getFullScore());
                //将所属大题的排序信息带给前端
                paperTopic.getItemData().setParentSort(answer.getItemMixSort());
                //将所属大题的题干附件信息带给前端 .
                paperTopic.getItemData().setParentStemAttrs(item.getStemAttrs());
                // 设置大题信息
                Integer topicSort = item.getTopicSort();
                List<PaperTopic> paperTopicList = this.getCandidatePaperTopicFromCache(examId, candidateId, candidatePaper.getId());
                Optional<PaperTopic> candidatePaperTopic = paperTopicList.stream().filter(p -> item.getTopicId().equals(p.getTopicId())).findFirst();
                if (candidatePaperTopic.isPresent() && StringUtils.isNotBlank(candidatePaperTopic.get().getTopicId())) {
                    topicSort = candidatePaperTopic.get().getSort();
                }
                paperTopic.setTopicId(item.getTopicId());
                paperTopic.setTopicName(item.getTopicName());
                paperTopic.setTopicDescription(item.getTopicDescription());
                paperTopic.setTopicSort(topicSort);
                paperTopic.setTopicScore(item.getTopicScore());
                paperTopic.setItemNumber(item.getItemNumber());
                // 增加翻译
                return this.translate(paperTopic, candidatePaper, language);
            }
        }


        // 构造小题信息
        paperTopic.setItemData(this.buildPaperItem(item, answer, isPracticeMode,examId,candidateId,paperSort));

        // 复合题：加载子小题，且只支持一级题
        if (PaperItemTypeCode.ITEM_TYPE_COMPOUND_CODE.getCode().equalsIgnoreCase(item.getItemType())
                || PaperItemTypeCode.ITEM_TYPE_CASE_ANALYSIS_CODE.getCode().equalsIgnoreCase(item.getItemType())
                //完型填空题也类似于复合
                || PaperItemTypeCode.ITEM_TYPE_CLOZE_FILL_IN_BLANKS_CODE.getCode().equalsIgnoreCase(item.getItemType())
                || PaperItemTypeCode.ITEM_TYPE_FILL_IN_BLANKS_CODE.getCode().equalsIgnoreCase(item.getItemType())
                || PaperItemTypeCode.ITEM_TYPE_MATCHING_CODE.getCode().equalsIgnoreCase(item.getItemType())) {
            List<CandidateAnswer> answerItemList = iCandidateAnswerService.list(
                    Wrappers.<CandidateAnswer>lambdaQuery().select(CandidateAnswer::getItemId,
                                    CandidateAnswer::getItemMixSort, CandidateAnswer::getOptionMixSortRule, CandidateAnswer::getStandardAnswer)
                            .eq(CandidateAnswer::getExamId, examId)
                            .eq(CandidateAnswer::getCandidateId, candidateId)
                            .eq(CandidateAnswer::getPaperId, candidatePaper.getPaperId())
                            .eq(CandidateAnswer::getPaperVersion, candidatePaper.getPaperVersion())
                            .eq(CandidateAnswer::getParentItemId, itemId)
                            .eq(CandidateAnswer::getDelFlag, false)
                            .orderByAsc(CandidateAnswer::getItemMixSort));
            List<PaperQuestionVO> childItemList = new ArrayList<>();
            String standardAnswer = "";
            Integer i = 1;
            for (CandidateAnswer candidateAnswer : answerItemList) {
                if(!PaperItemTypeCode.ITEM_TYPE_FILL_IN_BLANKS_CODE.getCode().equalsIgnoreCase(item.getItemType())) {
                    // 考务已经封装好子小题传过来
                    PItemDTO childItem = item.getChildItemMap().get(candidateAnswer.getItemId());
                    // 构建小题内容
                    PaperQuestionVO question = this.buildPaperItem(childItem, candidateAnswer, isPracticeMode,examId,candidateId,paperSort);
                    // 设置选项顺序
                    question.setItemSort(candidateAnswer.getItemMixSort());
                    childItemList.add(question);
                    paperTopic.getItemData().setChildItemList(childItemList);
                }
                if(isPracticeMode) {
                    standardAnswer += "(" + i + ")" + candidateAnswer.getStandardAnswer() + ",";
                }
                i++;
            }
            if(isPracticeMode && standardAnswer.endsWith(",")) {
                standardAnswer = standardAnswer.substring(0, standardAnswer.length()-1);
                PaperQuestionVO paperQuestion =  paperTopic.getItemData();
                paperQuestion.setStandardAnswer(standardAnswer);
                paperTopic.setItemData(paperQuestion);
            }

        }
        // 设置大题信息
        Integer topicSort = item.getTopicSort();
        List<PaperTopic> paperTopicList = this.getCandidatePaperTopicFromCache(examId, candidateId, candidatePaper.getId());
        Optional<PaperTopic> candidatePaperTopic = paperTopicList.stream().filter(p -> item.getTopicId().equals(p.getTopicId())).findFirst();
        if (candidatePaperTopic.isPresent() && StringUtils.isNotBlank(candidatePaperTopic.get().getTopicId())) {
            topicSort = candidatePaperTopic.get().getSort();
        }
        paperTopic.setTopicId(item.getTopicId());
        paperTopic.setTopicName(item.getTopicName());
        paperTopic.setTopicDescription(item.getTopicDescription());
        paperTopic.setTopicSort(topicSort);
        paperTopic.setTopicScore(item.getTopicScore());
        paperTopic.setItemNumber(item.getItemNumber());
        // 增加翻译
        return this.translate(paperTopic, candidatePaper, language);
    }

    private List<PaperTopic> getCandidatePaperTopicFromCache(String examId, String candidateId, String candidatePaperId) {
        String key = KeyDefineCommon.getCandidatePaperTopicKey(examId, candidateId, candidatePaperId);
        Object val = redisTemplate.opsForValue().get(key);
        if(val == null) {
            return this.putCandidatePaperTopicFromCache(examId, candidateId, candidatePaperId, 6, TimeUnit.HOURS);
        } else {
            return JSON.parseArray(val.toString(), PaperTopic.class);
        }
    }

    private List<PaperTopic> putCandidatePaperTopicFromCache(String examId, String candidateId, String candidatePaperId,
                                                     Integer timeout, TimeUnit timeUnit) {
        String key = KeyDefineCommon.getCandidatePaperTopicKey(examId, candidateId, candidatePaperId);
        List<PaperTopic> paperTopicList = paperTopicMapper.selectList(Wrappers.<PaperTopic>lambdaQuery().eq(PaperTopic::getCandidatePaperId, candidatePaperId));
        redisTemplate.opsForValue().set(key, JSON.toJSONString(paperTopicList), timeout, timeUnit);
        return paperTopicList;
    }

    private PaperBigQuestionVO translate(PaperBigQuestionVO paperTopic, CandidatePaper candidatePaper, String language) {
        paperTopic.setTranslateState(true);
        if(!TranslateLanguageCode.ZH.getCode().equalsIgnoreCase(language)) {
            try {
                PaperBigQuestionVO copy = new PaperBigQuestionVO();
                BeanUtils.copyProperties(paperTopic,copy);
//                        PaperBigQuestionVO copy = ObjectUtil.cloneByStream(paperTopic);
                if (PaperItemTypeCode.ITEM_TYPE_COMPOUND_CODE.getCode().equalsIgnoreCase(paperTopic.getItemData().getItemType())) {
                    // 翻译子小题
                    for (PaperQuestionVO it : copy.getItemData().getChildItemList()) {
                        this.translateItem(candidatePaper.getPaperId(), candidatePaper.getPaperVersion(), language, it);
                    }
                }
                this.translateItem(candidatePaper.getPaperId(), candidatePaper.getPaperVersion(), language, copy.getItemData());
                return copy;
            } catch (KsBizRunTimeException e) {
                paperTopic.setTranslateState(false);
            }
        }
        return paperTopic;
    }

    /**
     *
     * @param paperId
     * @param paperVersion
     * @param language
     * @param item 小题信息
     */
    private void translateItem(String paperId, String paperVersion, String language, PaperQuestionVO item) {
        String s = this.getTranslate(paperId, paperVersion, item.getItemId(), language);
        if (StringUtils.isBlank(s)) {
            throw new KsBizRunTimeException();
        }
        item.setItemContent(s);
        // 翻译选项，填空题除外
        if (item.getOptionsDataList() != null
                && !PaperItemTypeCode.ITEM_TYPE_FILL_IN_BLANKS_CODE.getCode().equalsIgnoreCase(item.getItemType())) {
            for (TopicOptionVO i : item.getOptionsDataList()) {
                String c = this.getTranslate(paperId, paperVersion, i.getOptionId(), language);
                if (StringUtils.isBlank(c)) {
                    throw new KsBizRunTimeException();
                }
                i.setOptionContent(c);
            }
        }
    }

    /**
     * 对小题选项进行排序，按照初始化试卷时定义的顺序，重新排序
     * @param itemData
     * @param item
     * @param ca
     */
    private void setOptions(PaperQuestionVO itemData, PItemDTO item, CandidateAnswer ca) {
        String standerAnswer = itemData.getStandardAnswer();
        // 过滤填空题
        if (PaperItemTypeCode.ITEM_TYPE_FILL_IN_BLANKS_CODE.getCode().equalsIgnoreCase(itemData.getItemType())
                || PaperItemTypeCode.ITEM_TYPE_MATCHING_CODE.getCode().equalsIgnoreCase(itemData.getItemType())
                || PaperItemTypeCode.ITEM_TYPE_MATCHING_CHILD_CODE.getCode().equalsIgnoreCase(itemData.getItemType())
                || PaperItemTypeCode.ITEM_TYPE_CLOZE_FILL_IN_BLANKS_CHILD_CODE.getCode().equalsIgnoreCase(itemData.getItemType())) {
            List<TopicOptionVO> topicOptions = new ArrayList<TopicOptionVO>();
            item.getOptionMap().forEach((k, v) -> {
                TopicOptionVO topicOption = new TopicOptionVO();
                topicOption.setOptionId(v.getOptionId());
                topicOption.setOptionSort(v.getOptionSort());
                topicOption.setOptionName(v.getOptionName());
                if(PaperItemTypeCode.ITEM_TYPE_CLOZE_FILL_IN_BLANKS_CHILD_CODE.getCode().equalsIgnoreCase(itemData.getItemType())
                        || PaperItemTypeCode.ITEM_TYPE_MATCHING_CODE.getCode().equalsIgnoreCase(itemData.getItemType())
                        || PaperItemTypeCode.ITEM_TYPE_MATCHING_CHILD_CODE.getCode().equalsIgnoreCase(itemData.getItemType())) {
                    topicOption.setOptionContent(v.getOptionContent());
                    topicOption.setOptionValue(v.getOptionName());
                    topicOption.setOptionAttrs(v.getOptionAttrs());
                }
                topicOptions.add(topicOption);
            });
            // 填空题不乱序
            itemData.setOptionsDataList(topicOptions.stream().sorted(
                    Comparator.comparing(TopicOptionVO::getOptionSort)).collect(Collectors.toList()));
        } else {
            String optionMixSortRule = ca.getOptionMixSortRule();
            // 除了填空题，其他主观题没有选项
            if (StringUtils.isNotBlank(optionMixSortRule)) {
                String[] arr = optionMixSortRule.split(",");
                List<TopicOptionVO> topicOptionVOList = new ArrayList<>();
                // 判断题
                if (PaperItemTypeCode.ITEM_TYPE_JUDGMENT_CODE.getCode().equalsIgnoreCase(itemData.getItemType())) {
                    for (String s : arr) {
                        TopicOptionVO topicOptionVO = new TopicOptionVO();
                        topicOptionVO.setOptionId(s);
                        topicOptionVO.setOptionContent("0".equals(s) ? "错" : "对");
                        // 错：0,对：1
                        topicOptionVO.setOptionValue("0".equals(s) ? "0" : "1");
                        if(StringUtils.isNotBlank(standerAnswer)){
                            itemData.setStandardAnswer("0".equals(standerAnswer) ? "错" : "对");
                        }
                        topicOptionVOList.add(topicOptionVO);
                    }
                } else {
                    // 单选、多选题
                    for (int i = 0; i < arr.length; i++) {
                        String s = arr[i];
                        POptionDTO option = item.getOptionMap().get(s);
                        TopicOptionVO topicOption = new TopicOptionVO();
                        topicOption.setOptionId(option.getOptionId());
                        topicOption.setOptionContent(option.getOptionContent());
                        // 填空题的时候，optionContent存的是标答，所以要去调不显示
                        if (!PaperItemTypeCode.ITEM_TYPE_FILL_IN_BLANKS_CODE.getCode().equalsIgnoreCase(itemData.getItemType())) {
                            topicOption.setOptionContent(option.getOptionContent());
                        }
                        topicOption.setOptionValue(option.getOptionName());
                        topicOption.setOptionName(Constants.ABC_ARRAY[i]);
                        //标答修改为乱序后的标答
                        if (StringUtils.isNotBlank(standerAnswer) && standerAnswer.equals(topicOption.getOptionValue())) {
                            itemData.setStandardAnswer(Constants.ABC_ARRAY[i]);
                        }

                        topicOption.setOptionAttrs(option.getOptionAttrs());
                        topicOptionVOList.add(topicOption);
                    }
                }
                itemData.setOptionsDataList(topicOptionVOList);
            }
        }
    }

    private PaperQuestionVO buildPaperItem(PItemDTO item, CandidateAnswer answer, boolean isPracticeMode,String examId,
                                           String candidateId,Integer paperSort) {
        PaperQuestionVO paperItem = new PaperQuestionVO();
        paperItem.setItemId(item.getItemId());
        paperItem.setItemType(item.getItemType());
        paperItem.setItemSort(answer.getItemMixSort());
        paperItem.setItemContent(item.getItemContent());
        if(isPracticeMode) {
            paperItem.setStandardAnswer(item.getStandardAnswer());
            paperItem.setDescription(item.getItemDescription());
        }

        paperItem.setStemAttrs(item.getStemAttrs());
        paperItem.setAnswerAttrs(item.getAnswerAttrs());
        paperItem.setDescriptionAttrs(item.getDescriptionAttrs());
        paperItem.setAttrsDataList(item.getAttrsDataList());
        paperItem.setScore(item.getScore());
        //设置作答时长  开启了单题限制
        if(Objects.equals(item.getOpenItemTiming(),Boolean.TRUE)){
            setOpenTime(paperItem,item,examId,candidateId,paperSort,answer);
        }
        this.setOptions(paperItem, item, answer);
        return paperItem;
    }

    private String getTranslate(String paperId, String paperVersion, String id, String language) {
        return iExamCacheService.getPaperTranslateCache(paperId, paperVersion, id, language);
    }

    private void setOpenTime(PaperQuestionVO paperItem,PItemDTO item,String examId,
                             String candidateId,Integer paperSort,CandidateAnswer answer){
        Long outTimeMinSecond = Objects.isNull(item.getOutTimeSecond()) ? 0L : (item.getOutTimeSecond() * 1000);
        paperItem.setOpenItemTiming(item.getOpenItemTiming());
        paperItem.setOutTimeSecond(outTimeMinSecond);
        //去判断剩余时长
        Long answerTime = 0L;
        //说明自己不是子小题
        if(StringUtils.isBlank(item.getItemPid())){
            answerTime = iAnswerProgressService.getByExamIdAndCandidateId(examId, candidateId, paperSort,item.getItemId(),null);
        } else {
            answerTime = iAnswerProgressService.getByExamIdAndCandidateId(examId, candidateId, paperSort,item.getItemPid(),item.getItemId());
        }
        if(Objects.equals(answerTime,0L)){
            //还没有作答过
            paperItem.setSurplusTime(outTimeMinSecond);
            paperItem.setAnswerTime(0L);
            return;
        }
        paperItem.setAnswerTime(answerTime);
        paperItem.setSurplusTime(outTimeMinSecond - answerTime);
    }
}
